import random
from datetime import datetime

import barcode
from barcode.writer import ImageWriter
from dateutil.relativedelta import relativedelta
from mrz.generator.td1 import TD1CodeGenerator
from PIL import Image, ImageDraw, ImageEnhance, ImageFilter, ImageFont
from transliterate import translit

from common_utils import paste_watermark

from .kz_utils import is_kazakh, kz_transliterate
import random
from datetime import datetime

import barcode
from PIL import Image, ImageDraw, ImageEnhance, ImageFilter, ImageFont
from barcode.writer import ImageWriter
from dateutil.relativedelta import relativedelta
from mrz.generator.td1 import TD1CodeGenerator
from transliterate import translit

from common_utils import paste_watermark
from .kz_utils import is_kazakh, kz_transliterate


# from create_bot import BASE_DIR


# def kz_id_new_generate(data, result_queue):
def kz_id_new_generate(data, result_queue):
    with Image.open("./files/kz/kz_id_new/bg_front.png").convert("RGBA") as bg_front:
        draw = ImageDraw.Draw(bg_front)
        font = ImageFont.truetype("fonts/tahoma.TTF", 31)
        fill = 170
        space = 4
        y_correction = 10
        resizing_correction = 4

        front_fields = [
            {
                "key": "name",
                "value": data["name"],
                "pos": (390, 316 - y_correction),
                "angle": 0,
                "fill": fill,
            },
            {
                "key": "last_name",
                "value": data["last_name"],
                "pos": (390, 232 - y_correction),
                "angle": 0,
                "fill": fill,
            },
            {
                "key": "middle_name",
                "value": data["middle_name"],
                "pos": (390, 404 - y_correction),
                "angle": 0,
                "fill": fill,
            },
            # {'key': 'nationality', 'value': data['nationality'], 'pos': (1498 - (font.getbbox(data['nationality'])[2] - font.getbbox(data['nationality'])[0]) / 2, 535), 'angle': 0, 'fill': fill},
            {
                "key": "date_of_birth",
                "value": data["date_of_birth"],
                "pos": (390, 491 - y_correction),
                "angle": 0,
                "fill": fill,
            },
            # {'key': 'place_of_birth', 'value': data['place_of_birth'], 'pos': (1756, 3072), 'angle': 0, 'fill': fill},
            # {'key': 'sex', 'value': data['sex'], 'pos': (1758, 2921), 'angle': 0, 'fill': fill},
            # {'key': 'issue_date', 'value': data['issue_date'], 'pos': (864, 3238), 'angle': 0, 'fill': fill},
            # {'key': 'date_of_expiry', 'value': data['date_of_expiry'], 'pos': (865, 3389), 'angle': 0, 'fill': fill},
            # {'key': 'authority', 'value': data['authority'], 'pos': (864, 3547), 'angle': 0, 'fill': fill},
            # {'key': 'id_new_number', 'value': data['id_new_number'], 'pos': (2157, 2378), 'angle': 0, 'fill': fill},
            {
                "key": "jsn",
                "value": data["jsn"],
                "pos": (148, 588 - y_correction),
                "angle": 0,
                "fill": fill,
            },
        ]

        for field in front_fields:
            x = field["pos"][0]
            y = field["pos"][1]
            now_font = font
            now_space = space
            for i in field["value"]:
                if field["key"] == "jsn":
                    now_font = ImageFont.truetype("fonts/8331.ttf", 40)
                    now_space = -3
                line_height = sum(now_font.getmetrics())
                fontimage = Image.new(
                    "L", (now_font.getbbox(i)[2] - now_font.getbbox(i)[0], line_height)
                )
                ImageDraw.Draw(fontimage).text((0, 0), i, field["fill"], font=now_font)
                if field["key"] != "jsn":
                    fontimage = fontimage.resize(
                        (
                            (
                                now_font.getbbox(i)[2]
                                - now_font.getbbox(i)[0]
                                - resizing_correction
                            ),
                            line_height,
                        )
                    )

                fontimage = fontimage.rotate(
                    field["angle"], resample=Image.BICUBIC, expand=True
                )
                fontimage = fontimage.filter(ImageFilter.MaxFilter(1))
                fontimage = fontimage.filter(ImageFilter.EDGE_ENHANCE)
                fontimage = fontimage.filter(
                    ImageFilter.UnsharpMask(radius=1, percent=400, threshold=5)
                )
                fontimage = fontimage.filter(ImageFilter.GaussianBlur(1.2))
                bg_front.paste((0, 0, 0), box=(x, y), mask=fontimage)
                x += (
                    now_font.getbbox(i)[2]
                    - now_font.getbbox(i)[0]
                    - resizing_correction
                ) + now_space

        # fontimage = Image.new('L', (font_dotted.getbbox(field['value'])[2] - font_dotted.getbbox(field['value'])[0], line_height))

        with Image.open(f'./files/kz/kz_id_new/photo_usr/{data["id"]}_w.png').convert(
            "RGBA"
        ) as photo:
            photo = photo.resize((297, 390))
            photo_layer = Image.new("RGBA", (297, 390), color=(1, 1, 1, 120))
            layer = Image.new("RGBA", bg_front.size, (255, 255, 255, 0))
            layer.paste(photo_layer, box=(42, 180 - y_correction), mask=photo_layer)
            bg_front = Image.alpha_composite(bg_front, layer)
            # bg_front.paste(photo_layer, box=(42, 180 - y_correction), mask=photo_layer)
            photo = ImageEnhance.Color(photo).enhance(0.4)
            photo = ImageEnhance.Brightness(photo).enhance(1.1)
            photo = ImageEnhance.Contrast(photo).enhance(0.7)
            photo = photo.rotate(0, resample=Image.BICUBIC, expand=True)
            photo = photo.filter(ImageFilter.GaussianBlur(1.5))
            layer = Image.new("RGBA", bg_front.size, (255, 255, 255, 0))
            layer.paste(photo, box=(42, 180 - y_correction), mask=photo)
            bg_front = Image.alpha_composite(bg_front, layer)
            # bg_front.paste(photo, box=(42, 180 - y_correction), mask=photo)

        with Image.open(f'./files/kz/kz_id_new/photo_usr/{data["id"]}_w.png').convert(
            "RGBA"
        ) as photo_2:
            photo_2 = photo_2.resize((108, 141))
            photo_layer = Image.new("RGBA", (108, 141), color=(1, 1, 1, 100))
            layer = Image.new("RGBA", bg_front.size, (255, 255, 255, 0))
            layer.paste(photo_layer, box=(863, 140 - y_correction), mask=photo_layer)
            bg_front = Image.alpha_composite(bg_front, layer)
            # bg_front.paste(layer, box=(863, 140 - y_correction), mask=layer)
            pixel_data = photo_2.load()
            # Изменит альфа-канал каждого пикселя на указанный процент его исходной прозрачности
            transparency_percent = 50
            for y in range(photo_2.size[1]):
                for x in range(photo_2.size[0]):
                    old_alpha = pixel_data[x, y][3]
                    new_alpha = int(old_alpha * transparency_percent / 100)
                    pixel_data[x, y] = (
                        pixel_data[x, y][0],
                        pixel_data[x, y][1],
                        pixel_data[x, y][2],
                        new_alpha,
                    )
            # photo_2.putalpha(128)
            # layer = Image.new('RGBA', bg_front.size, color = (0, 0, 0, 0))
            # layer.paste(photo_2, box=(863, 140 - y_correction), mask=photo_2)
            # layer = Image.new('RGBA', (108, 141), color = (255, 255, 255, 100))
            # layer.putalpha(50)
            # bg_front.paste(layer, box=(863, 140 - y_correction), mask=layer)
            photo_2 = ImageEnhance.Color(photo_2).enhance(0)
            photo_2 = ImageEnhance.Brightness(photo_2).enhance(0.6)
            photo_2 = ImageEnhance.Contrast(photo_2).enhance(3.0)
            # photo_2 = photo_2.rotate(0, resample=Image.BICUBIC, expand=True)
            # photo_2 = photo_2.filter(ImageFilter.GaussianBlur(1.5))
            # bg_front = Image.alpha_composite(bg_front, photo_2)
            layer = Image.new("RGBA", bg_front.size, (255, 255, 255, 0))
            layer.paste(photo_2, box=(863, 140 - y_correction), mask=photo_2)
            bg_front = Image.alpha_composite(bg_front, layer)
            # bg_front.paste(photo_2, box=(863, 140 - y_correction), mask=photo_2)

        # Генерация и рендер подписи
        sign = data["sign"].capitalize()
        if is_kazakh(sign):
            sign = kz_transliterate(sign)
        if data["signature"] != 0:
            fonts_dict = {
                1: ImageFont.truetype("./fonts/1_ru.ttf", size=90),
                2: ImageFont.truetype("./fonts/2_ru.ttf", size=60),
                3: ImageFont.truetype("./fonts/3_ru.ttf", size=70),
                4: ImageFont.truetype("./fonts/4_ru.otf", size=60),
                5: ImageFont.truetype("./fonts/5_ru.ttf", size=55),
                6: ImageFont.truetype("./fonts/6_ru.ttf", size=55),
                7: ImageFont.truetype("./fonts/66.ttf", size=40),
            }
            font = fonts_dict[data["signature"]]
            width = font.getbbox(sign)[2] - font.getbbox(sign)[0]
            height = font.getbbox(sign)[3] - font.getbbox(sign)[1]
            txt = Image.new(
                "RGBA",
                (width + (width // 5), height + (height // 5)),
                (255, 255, 255, 0),
            )
            draw = ImageDraw.Draw(txt)
            draw.text(
                xy=(width // 10, height // 10),
                text=sign,
                font=font,
                fill=(0, 0, 0, 230),
                stroke_width=0,
                anchor="lt",
            )
            txt = txt.resize((200, 100))
            layer = Image.new("RGBA", bg_front.size, (255, 255, 255, 0))
            layer.paste(txt, box=(605, 515), mask=txt)
            bg_front = Image.alpha_composite(bg_front, layer)
            # bg_front.paste(txt, box=(605, 515), mask=txt)
            if data["signature"] == 6:
                font66 = fonts_dict[7]
                width66 = font66.getbbox("k")[2] - font66.getbbox("k")[0]
                height66 = font66.getbbox("k")[3] - font66.getbbox("k")[1]
                txt = Image.new(
                    "RGBA",
                    (width66 + (width66 // 5), height66 + (height66 // 5)),
                    (255, 255, 255, 0),
                )
                draw = ImageDraw.Draw(txt)
                draw.text(
                    xy=(width66 // 10, height66 // 10),
                    text="k",
                    font=fonts_dict[7],
                    fill=(0, 0, 0, 230),
                    anchor="lt",
                )
                txt = txt.resize((180, 30))
                layer = Image.new("RGBA", bg_front.size, (255, 255, 255, 0))
                layer.paste(
                    txt, box=(605 + width // 4, 500 + height - (height // 6)), mask=txt
                )
                bg_front = Image.alpha_composite(bg_front, layer)
                # bg_front.paste(txt, box=(605 + width // 4, 500 + height - (height // 6)), mask=txt)

    with Image.open("./files/kz/kz_id_new/bg_back.png").convert("RGBA") as bg_back:
        draw = ImageDraw.Draw(bg_back)
        font = ImageFont.truetype("fonts/tahoma.TTF", 31)
        font_mrz = ImageFont.truetype("./fonts/OCR B Pro.TTF", 43)
        fill = 170
        space = 3
        y_correction = 10
        resizing_correction = 4

        ten_years = relativedelta(years=10)
        one_day = relativedelta(days=1)
        data["date_of_expiry"] = (
            datetime.strptime(data["issue_date"], "%d.%m.%Y") + ten_years - one_day
        ).strftime("%d.%m.%Y")
        data["type"] = "ID"
        data["code_of_state"] = "KAZ"
        data["authority"] = "МВД РЕСПУБЛИКИ КАЗАХСТАН"

        back_fields = [
            {
                "key": "nationality",
                "value": data["nationality"],
                "pos": (288, 193 - y_correction),
                "angle": 0,
                "fill": fill,
            },
            {
                "key": "place_of_birth",
                "value": data["place_of_birth"],
                "pos": (288, 131 - y_correction),
                "angle": 0,
                "fill": fill,
            },
            # {'key': 'sex', 'value': data['sex'], 'pos': (1758, 2921), 'angle': 0, 'fill': fill},
            {
                "key": "issue_date",
                "value": data["issue_date"],
                "pos": (288, 325 - y_correction),
                "angle": 0,
                "fill": fill,
            },
            {
                "key": "date_of_expiry",
                "value": data["date_of_expiry"],
                "pos": (503, 325 - y_correction),
                "angle": 0,
                "fill": fill,
            },
            {
                "key": "authority",
                "value": data["authority"],
                "pos": (288, 260 - y_correction),
                "angle": 0,
                "fill": fill,
            },
            {
                "key": "id_new_number",
                "value": data["id_new_number"],
                "pos": (692, 35 - y_correction),
                "angle": 0,
                "fill": fill + 20,
            },
        ]

        for field in back_fields:
            x = field["pos"][0]
            y = field["pos"][1]
            now_font = font
            now_space = space
            for i in field["value"]:
                if field["key"] == "id_new_number":
                    now_font = ImageFont.truetype("fonts/8331.ttf", 44)
                    now_space = 0
                line_height = sum(now_font.getmetrics())
                fontimage = Image.new(
                    "L", (now_font.getbbox(i)[2] - now_font.getbbox(i)[0], line_height)
                )
                ImageDraw.Draw(fontimage).text((0, 0), i, field["fill"], font=now_font)

                if field["key"] != "id_new_number":
                    fontimage = fontimage.resize(
                        (
                            (
                                now_font.getbbox(i)[2]
                                - now_font.getbbox(i)[0]
                                - resizing_correction
                            ),
                            line_height,
                        )
                    )

                fontimage = fontimage.rotate(
                    field["angle"], resample=Image.BICUBIC, expand=True
                )
                fontimage = fontimage.filter(ImageFilter.MaxFilter(1))
                fontimage = fontimage.filter(ImageFilter.EDGE_ENHANCE)
                fontimage = fontimage.filter(
                    ImageFilter.UnsharpMask(radius=1, percent=400, threshold=5)
                )
                fontimage = fontimage.filter(ImageFilter.GaussianBlur(1.2))
                bg_back.paste((0, 0, 0), box=(x, y), mask=fontimage)
                x += (
                    now_font.getbbox(i)[2]
                    - now_font.getbbox(i)[0]
                    - resizing_correction
                ) + now_space

        bar = barcode.get("code128", data["jsn"], writer=ImageWriter())
        bar = bar.render().convert("RGBA")
        bar = bar.crop((20, 20, 280, 80))
        datas = bar.getdata()

        newData = []
        for item in datas:
            if item[0] == 255 and item[1] == 255 and item[2] == 255:
                newData.append((255, 255, 255, 0))
            else:
                newData.append((0, 0, 0, 180))

        bar.putdata(newData)
        bar = bar.resize((355, 55))
        bg_back.paste(bar, box=(48, 20), mask=bar)

        name = data["name"]
        last_name = data["last_name"]
        if is_kazakh(name):
            name = kz_transliterate(name)
        if is_kazakh(last_name):
            last_name = kz_transliterate(last_name)

        tr_name = translit(name, language_code="ru", reversed=True)
        tr_last_name = translit(last_name, language_code="ru", reversed=True)
        mrz_code = TD1CodeGenerator(
            data["type"],
            data["code_of_state"],
            data["id_new_number"],
            data["date_of_birth"][8:]
            + data["date_of_birth"][3:5]
            + data["date_of_birth"][0:2],
            data["sex"],
            data["date_of_expiry"][8:]
            + data["date_of_expiry"][3:5]
            + data["date_of_expiry"][0:2],
            data["code_of_state"],
            tr_last_name,
            tr_name,
            data["jsn"],
        )
        mrz_strs = str(mrz_code).split("\n")

        fontimage = Image.new(
            "L",
            (
                font_mrz.getbbox(mrz_strs[0])[2] - font_mrz.getbbox(mrz_strs[0])[0],
                sum(font_mrz.getmetrics()),
            ),
        )
        ImageDraw.Draw(fontimage).text((0, 0), mrz_strs[0], fill=200, font=font_mrz)
        fontimage = fontimage.filter(ImageFilter.MaxFilter(1))
        fontimage = fontimage.filter(ImageFilter.EDGE_ENHANCE)
        fontimage = fontimage.filter(
            ImageFilter.UnsharpMask(radius=1, percent=400, threshold=5)
        )
        fontimage = fontimage.filter(ImageFilter.GaussianBlur(1.2))
        bg_back.paste((0, 0, 0), box=(54, 412), mask=fontimage)

        fontimage = Image.new(
            "L",
            (
                font_mrz.getbbox(mrz_strs[1])[2] - font_mrz.getbbox(mrz_strs[1])[0],
                sum(font_mrz.getmetrics()),
            ),
        )
        ImageDraw.Draw(fontimage).text((0, 0), mrz_strs[1], fill=200, font=font_mrz)
        fontimage = fontimage.filter(ImageFilter.MaxFilter(1))
        fontimage = fontimage.filter(ImageFilter.EDGE_ENHANCE)
        fontimage = fontimage.filter(
            ImageFilter.UnsharpMask(radius=1, percent=400, threshold=5)
        )
        fontimage = fontimage.filter(ImageFilter.GaussianBlur(1.2))
        bg_back.paste((0, 0, 0), box=(54, 478), mask=fontimage)

        fontimage = Image.new(
            "L",
            (
                font_mrz.getbbox(mrz_strs[2])[2] - font_mrz.getbbox(mrz_strs[2])[0],
                sum(font_mrz.getmetrics()),
            ),
        )
        ImageDraw.Draw(fontimage).text((0, 0), mrz_strs[2], fill=200, font=font_mrz)
        fontimage = fontimage.filter(ImageFilter.MaxFilter(1))
        fontimage = fontimage.filter(ImageFilter.EDGE_ENHANCE)
        fontimage = fontimage.filter(
            ImageFilter.UnsharpMask(radius=1, percent=400, threshold=5)
        )
        fontimage = fontimage.filter(ImageFilter.GaussianBlur(1.2))
        bg_back.paste((0, 0, 0), box=(54, 541), mask=fontimage)

        bg_front = bg_front.resize((1012, 638))
        bg_back = bg_back.resize((1012, 638))
        image_name = f'./files/kz/kz_id_new/photo_usr/{data["id"]}_completed'
        if data["size"] == "DOC":
            bg = Image.new("RGBA", (1012 * 2 + 10, 638), (255, 255, 255, 255))
            bg.paste(bg_front, box=(0, 0), mask=bg_front)
            bg.paste(bg_back, box=((1012 + 10), 0), mask=bg_back)
            pixel_data = bg.load()
            for y in range(bg.size[1]):
                for x in range(bg.size[0]):
                    r, g, b, alpha = (
                        pixel_data[x, y][0],
                        pixel_data[x, y][1],
                        pixel_data[x, y][2],
                        pixel_data[x, y][3],
                    )
                    if (r, g, b) == (255, 255, 255):
                        pixel_data[x, y] = (r, g, b, 0)
            bg.save(image_name + ".png")
            result_queue.put(image_name)
        elif data["size"] == "A4":
            bg = Image.new("RGB", (2481, 3507), (255, 255, 255))
            bg_front = bg_front.rotate(
                random.uniform(-0.9, 0.9), resample=Image.BICUBIC, expand=True
            )
            bg_back = bg_back.rotate(
                random.uniform(-0.9, 0.9), resample=Image.BICUBIC, expand=True
            )
            bg.paste(bg_front, box=(120, 120), mask=bg_front)
            bg.paste(bg_back, box=((1020 + 30 + 110), 120), mask=bg_back)
            bg.save(image_name + ".png")
            result_queue.put(image_name)

    image_path = f'./files/kz/kz_id_new/photo_usr/{data["id"]}_completed.png'
    path_to_save = f'./files/kz/kz_id_new/photo_usr/{data["id"]}_completed_wm.png'
    paste_watermark(image_path, path_to_save)


exemplary_data = {
    "name": "КЕТ",
    "last_name": "КЕТМЕН",
    "middle_name": "ҚАЗАҚ",
    "nationality": "КАЗАХ",
    "date_of_birth": "14.06.1946",
    "place_of_birth": "KAZAKHSTAN",
    "sex": "M",
    "issue_date": "24.05.2018",
    "authority": "CIA",
    "id_new_number": "012345678",
    "jsn": "123456789123",
    "signature": 6,
    "sign": "КЕТ",
    "size": "DOC",
    "id": "276802147",
}

# kz_id_new_generate(exemplary_data, queue.Queue())
"""
if __name__ == "__main__":
    try:
        kz_id_new_generate(exemplary_data, queue.Queue())
    except:
        print("Ошибка")
        id_new
"""
